package com.toft.widgets.workflow.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;
import org.jbpm.api.JbpmException;
import org.jbpm.api.model.OpenExecution;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.task.TaskImpl;

import com.toft.widgets.workflow.authorization.IAuthorizedManagement;
import com.toft.widgets.workflow.factory.ServiceFactory;
import com.toft.widgets.workflow.factory.impl.ServiceFactoryImpl;
import com.toft.widgets.workflow.model.DynamicTaskInfo;
import com.toft.widgets.workflow.model.TaskHastenInfo;
import com.toft.widgets.workflow.model.WorkflowUser;
import com.toft.widgets.workflow.service.IDynamicTaskService;
import com.toft.widgets.workflow.service.IRegulationService;
import com.toft.widgets.workflow.service.ITaskMessageService;
import com.toft.widgets.workflow.service.JbpmServiceSupport;
import com.toft.widgets.workflow.service.WorkflowFacade;
import com.toft.widgets.workflow.taskrole.Assignable;
import com.toft.widgets.workflow.utils.ConstantUtil;

/**
 * 任务服务接口实现类
 * 
 * @author 邹庆林
 * @version 1.0
 */
public class DynamicTaskServiceImpl extends JbpmServiceSupport implements IDynamicTaskService {

	public void assignTaskParticipator(org.jbpm.api.task.Assignable assignable, String assignRule, TaskHastenInfo taskHastenInfo,
			DynamicTaskInfo dynamicTaskInfo) {

		List hasten = taskHastenInfo.getHasten();
		String hastenTemplate = taskHastenInfo.getHastenTemplate();
		String taskUrl = dynamicTaskInfo.getTaskUrl();
		ExecutionImpl execution = (ExecutionImpl) dynamicTaskInfo.getExecution();
		TaskImpl task = (TaskImpl) assignable;

		// 从流程变量中获取机构和部门标识，即模块和客户的标识
		Map variables = execution.getVariables();
		String selectedUser = (String) variables.get(ConstantUtil.SELECT_USER_CODE);
		String loginUser = (String) variables.get(ConstantUtil.USER_CODE);
		copyVariablesToTask(variables, task);
		String agencyId = task.getAgencyId();
		String departmentId = task.getDepartmentId();
		String businessType = task.getBusinessType();
		String userCode = "";

		// 循环节点动态参与者规则赋值
		Object department;
		Object user;
		ExecutionImpl parent = ((ExecutionImpl) execution).getSuperProcessExecution();
		if (parent != null) {
			department = parent.getVariables().get("department");
			user = parent.getVariables().get("user");
		} else {
			department = variables.get("department");
			user = variables.get("user");
		}
		if (department != null) {
			Map departmentMap = (HashMap) department;
			agencyId = (String) departmentMap.get("department");
			taskUrl = (String) departmentMap.get("url");
			logger.info("机构标识：" + agencyId + ",业务类型：" + businessType + ",流程变量：" + variables + ",业务URL：" + taskUrl);
		}

		if (user != null) {
			Map userMap = (HashMap) user;
			userCode = (String) userMap.get("user");
			taskUrl = (String) userMap.get("url");
			logger.info("用户标识：" + userCode + ",业务类型：" + businessType + ",流程变量：" + variables + ",业务URL：" + taskUrl);
		}

		if (StringUtils.isNotEmpty(taskUrl)) {
			task.setUrl(taskUrl);
		}

		if (selectedUser != null && !"".equals(selectedUser)) {
			task.setAssignee(selectedUser);
		} else {
			// 根据参与者规则代码获取参与者对象
			Assignable assignableObj = this.getRegulationService().getTaskParticipatorRule(assignRule, agencyId, departmentId, loginUser);
			String agentId = null;
			if (assignableObj == null) {
				throw new JbpmException("获取参与者规则错误.参与者规则编码：" + assignRule);
			}
			String assignableId = assignableObj.getAssignableId();
			if (user != null) {
				assignableId = userCode;
			}
			if (!assignableObj.isGroup() || user != null) {
				task.setAssignee(assignableId);
				task.setTaskType(ConstantUtil.COMMON_TASK);
				agentId = getAgentIdByUserCode(agencyId, departmentId, businessType, assignableId);
			} else {
				task.addCandidateGroup(assignableId);
				task.setTaskType(ConstantUtil.COMMON_GROUP_TASK);
				agentId = getAgentIdByGroupId(agencyId, departmentId, businessType, assignableId);
			}
			if (StringUtils.isNotEmpty(agentId)) {
				task.setAgentId(agentId);
			}
			// 获取消息模板所需要的占位符
			Map replace = this.getVariables(task); // 有可能获取不到变量，原因是此时任务未持久化
			if (null != hasten && hasten.size() > 0) {
				// 发送任务催办（催办任务的相关信息从taskHastenInfo获取）
				WorkflowUser sui = new WorkflowUser(agencyId, departmentId);
				this.taskHasten(hasten, assignableObj, hastenTemplate, replace, sui);
			}
		}
	}

	/**
	 * 查询组中用户的授权记录
	 * 
	 * @date 2011-6-9下午01:35:10
	 * @param agencyId
	 *            机构标识
	 * @param departmentId
	 *            部门标识
	 * @param businessType
	 *            业务类型标识
	 * @param groupId
	 *            岗位标识
	 * @return
	 */
	protected String getAgentIdByGroupId(String agencyId, String departmentId, String businessType, String groupId) {
		// 要获取业务授权记录，调用授权接口
		Map conditions = new HashMap();
		conditions.put(ConstantUtil.GROUPID, groupId);
		conditions.put(ConstantUtil.BUSINESS_TYPE, businessType);
		conditions.put(ConstantUtil.AGENCY_ID, agencyId);
		conditions.put(ConstantUtil.DEPARTMENT_ID, departmentId);
		conditions.put(ConstantUtil.CONN, WorkflowFacade.getConnection());
		// 查询组中用户的授权记录
		return this.getAuthorizedmanagement().getAgentIdByGroupId(conditions);
	}

	/**
	 * 查询用户的授权记录
	 * 
	 * @date 2011-6-9下午01:35:14
	 * @param agencyId
	 *            机构标识
	 * @param departmentId
	 *            部门标识
	 * @param businessType
	 *            业务类型标识
	 * @param userCode
	 *            用户标识
	 * @return
	 */
	protected String getAgentIdByUserCode(String agencyId, String departmentId, String businessType, String userCode) {
		// 要获取业务授权记录，调用授权接口，
		Map conditions = new HashMap();
		conditions.put(ConstantUtil.USER_CODE, userCode);
		conditions.put(ConstantUtil.BUSINESS_TYPE, businessType);
		conditions.put(ConstantUtil.AGENCY_ID, agencyId);
		conditions.put(ConstantUtil.DEPARTMENT_ID, departmentId);
		conditions.put(ConstantUtil.CONN, WorkflowFacade.getConnection());
		// 查询用户的授权记录
		return this.getAuthorizedmanagement().getAuths(conditions);

	}

	// 会签任务
	public void createCounterSignature(String counterSignatureRule, org.jbpm.api.task.Assignable assignable, TaskHastenInfo taskHastenInfo,
			DynamicTaskInfo dynamicTaskInfo) {

		Session session = WorkflowFacade.getSession();
		String taskUrl = dynamicTaskInfo.getTaskUrl();
		OpenExecution execution = dynamicTaskInfo.getExecution();

		// 从流程变量中获取机构和部门标识，即模块和客户的标识
		Map variables = execution.getVariables();
		String loginUser = (String) variables.get(ConstantUtil.LOGIN_USER_CODE);
		if ((null != counterSignatureRule) || (!"".equals(counterSignatureRule))) {
			List hasten = new ArrayList();
			String templateCode = "";
			if (null != taskHastenInfo) {
				hasten = taskHastenInfo.getHasten();
				templateCode = taskHastenInfo.getHastenTemplate();
			}

			TaskImpl parentTask = (TaskImpl) assignable;
			// 从流程变量中获取机构和部门标识，即模块和客户的标识
			parentTask.setUrl(taskUrl);
			copyVariablesToTask(variables, parentTask);
			String agencyId = parentTask.getAgencyId();
			String departmentId = parentTask.getDepartmentId();
			String businessType = parentTask.getBusinessType();

			// 通过counterSignatureRule获取岗位
			List users = this.getRegulationService().getCounterSignature(counterSignatureRule, agencyId, departmentId, loginUser);
			if (null != users && users.size() > 0) {
				Set subTasks = new HashSet();

				// 为父任务设置会签任务标识，父任务只是一个标识，无任务参与者
				parentTask.setTaskType(ConstantUtil.COUNTERSIGNATURE_TASK_PARENT);
				// parentTask.setTaskDefinition(parentTask.getTaskDefinition());
				// 获取消息模板所需要的占位符
				Map replace = this.getVariables(parentTask); // 有可能获取不到变量，原因是此时任务未持久化

				for (Iterator iter = users.iterator(); iter.hasNext();) {
					String userCode = (String) iter.next();
					TaskImpl subTask = parentTask.createSubTask();
					subTask.setSuperTask(parentTask);
					subTask.setSuperTaskDbid(new Long(parentTask.getDbid()));
					subTask.setExecution(parentTask.getExecution());
					subTask.setProcessInstance(parentTask.getProcessInstance());
					subTask.setUrl(taskUrl);
					copyVariablesToTask(variables, subTask);
					// 设置会签任务标识
					subTask.setTaskType(ConstantUtil.COUNTERSIGNATURE_TASK);
					subTask.setAssignee(userCode);
					subTask.setName(parentTask.getName() + "_counterSignatureTask");
					// 给子任务节点赋值中文名
					subTask.setActivityName(parentTask.getActivityName());

					// 为会签任务分配参与者时，要获取业务授权记录，调用授权接口，
					// 需要传给授权接口参数为业务类型（从流程变量中获取），
					// 用户code（assignable.getAssignableId()），
					// 根据返回的授权记录来为任务添加候选用户（代理人），
					// 同时将代理人标识放入到task的agentId字段（需要 修改JBPM4.1源码）

					String auths = getAgentIdByUserCode(agencyId, departmentId, businessType, userCode);

					if (StringUtils.isNotEmpty(auths)) {
						subTask.setAgentId(auths);
					}

					session.save(subTask);
					subTasks.add(subTask);
					if (null != hasten && hasten.size() > 0) {
						// 发送任务催办，给用户发送任务催办
						WorkflowUser sui = new WorkflowUser(agencyId, departmentId);
						this.getTaskMessageService().sendMessageToUser(userCode, templateCode, replace, hasten, sui);
					}

				}
				// 手动维护父子任务关系
				parentTask.setSubTasks(subTasks);
				session.save(parentTask);
			}

		}

	}

	protected void copyVariablesToTask(Map variables, TaskImpl task) {
		// 提交人
		String applicationUser = (String) variables.get(ConstantUtil.SUBMIT_USER);
		// 业务单据类型标识
		String businessType = variables.get(ConstantUtil.BUSINESS_TYPE) == null ? "" : (String) variables.get(ConstantUtil.BUSINESS_TYPE);
		// 业务类型名称
		String businessName = variables.get(ConstantUtil.BUSINESS_NAME) == null ? "" : (String) variables.get(ConstantUtil.BUSINESS_NAME);
		// 业务单据编号
		String businessSN = variables.get(ConstantUtil.BUSINESS_SN) == null ? "" : (String) variables.get(ConstantUtil.BUSINESS_SN);
		// 业务单据标识
		String businessRecordId = variables.get(ConstantUtil.BUSINESS_RECORE_ID) == null ? "" : (String) variables
				.get(ConstantUtil.BUSINESS_RECORE_ID);
		// 业务单据金额
		String businessMoney = variables.get(ConstantUtil.BUSINESS_MONEY) == null ? "" : (String) variables.get(ConstantUtil.BUSINESS_MONEY);
		// 机构ID
		String agencyId = variables.get(ConstantUtil.AGENCY_ID) == null ? "" : (String) variables.get(ConstantUtil.AGENCY_ID);
		// 部门ID
		String departmentId = variables.get(ConstantUtil.DEPARTMENT_ID) == null ? "" : (String) variables.get(ConstantUtil.DEPARTMENT_ID);
		// 扩展属性
		byte[] workflowObject = null;
		Object obj = variables.get(ConstantUtil.WORKFLOW_OBJECT);
		if (obj != null) {
			workflowObject = SerializationUtils.serialize((Serializable) obj);
		}
		task.setApplicationUser(applicationUser);
		task.setBusinessType(businessType);// 将业务类型持久化到任务属性中
		task.setBusinessName(businessName);
		task.setBusinessSN(businessSN);
		task.setBusinessRecordId(businessRecordId);
		task.setBusinessMoney(businessMoney);
		task.setAgencyId(agencyId);
		task.setDepartmentId(departmentId);
		task.setWorkflowObject(workflowObject);

		ExecutionImpl processInstance = task.getProcessInstance();
		ExecutionImpl superProcessInstance = processInstance.getSuperProcessExecution();
		if (superProcessInstance != null) {
			if (superProcessInstance.getParent() != null) {
				task.setExeId(superProcessInstance.getParent().getId());
			} else {
				task.setExeId(superProcessInstance.getId());
			}
		} else {
			task.setExeId(processInstance.getId());
		}
	}

	// 抄送
	public void taskCarbonCopy(List carbonCopy, Map replace) {

		if ((null != carbonCopy) && (carbonCopy.size() > 0)) {
			Map tempMap = new HashMap();

			String templateCode = ""; // 消息模板
			String tempCarbonCopyWay = ""; // 抄送方式
			String userCode = ""; // 抄送接收者

			String[] carbonCopyWay = {};

			List hasten = new ArrayList();

			for (Iterator iter = carbonCopy.iterator(); iter.hasNext();) {
				tempMap = (Map) iter.next();

				templateCode = (String) tempMap.get("hastenTemplate");
				userCode = (String) tempMap.get("receiverCode");
				tempCarbonCopyWay = (String) tempMap.get("carbonCopyWay");

				if (tempCarbonCopyWay.indexOf("$") != -1) {
					carbonCopyWay = tempCarbonCopyWay.split("\\$");
					hasten = Arrays.asList(carbonCopyWay);
				}

				this.getTaskMessageService().sendMessageToUser(userCode, templateCode, replace, hasten, null);

			}
		}

	}

	public void taskHasten(String hasten, String assignRule, String templateCode, Map replace) {
		// TODO Auto-generated method stub

	}

	// 任务催办
	public void taskHasten(List hasten, Assignable assignable, String hastenTemplate, Map replace, WorkflowUser sui) {

		if ((null == assignable) || "".equals(hastenTemplate) || (null == hasten)) {
			throw new JbpmException("缺失发送消息的参数！");
		}

		if (assignable.isGroup()) {

			// 给组发送任务催办
			this.getTaskMessageService().sendMessageToGroup(assignable.getAssignableId(), hastenTemplate, replace, hasten, sui);

		} else {

			// 给用户发送任务催办
			this.getTaskMessageService().sendMessageToUser(assignable.getAssignableId(), hastenTemplate, replace, hasten, sui);

		}

	}

	// 获取消息模板所需要的占位符
	private Map getVariables(TaskImpl task) {

		Map variables = task.getVariables();

		Map replace = new HashMap();
		Iterator iter = variables.keySet().iterator();
		String str = "";
		BigDecimal bd = null;
		while (iter.hasNext()) {
			String key = (String) iter.next();
			Object value = variables.get(key);

			if (value instanceof java.lang.Double) {
				bd = new BigDecimal(((java.lang.Double) value).doubleValue());
				str = bd.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
				// str = bd.setScale(2, 3).toString();
			} else if (value instanceof java.lang.Integer) {
				bd = new BigDecimal(((java.lang.Integer) value).intValue());
				str = bd.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
				// str = bd.setScale(2, 3).toString();
			} else if (value instanceof java.lang.Long) {
				bd = new BigDecimal(((java.lang.Long) value).longValue());
				str = bd.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
				// str = bd.setScale(2, 3).toString();
			} else if (value instanceof java.lang.Float) {
				bd = new BigDecimal(((java.lang.Float) value).floatValue());
				str = bd.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
				// str = bd.setScale(2, 3).toString();
			} else if (value instanceof java.util.Date) {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
				str = sdf.format(value);
			} else if (value instanceof java.lang.String) {
				str = value.toString();
			}
			replace.put(key, str);
		}

		return replace;
	}

	// 为动态任务分配任务参与者，要发送任务催办，
	// 将字符串的催办方式放入ArrayList中
	private List getHastenWay(String hastenWay) {

		List hastenWays = new ArrayList();

		String[] tempWays = {};

		if (null != hastenWay && !"".equals(hastenWay)) {
			tempWays = hastenWay.split("\\$");
			hastenWays = Arrays.asList(tempWays);
		}

		return hastenWays;
	}

	// 获取规则服务对象
	private IRegulationService getRegulationService() {

		ServiceFactory serviceFactory = ServiceFactoryImpl.getServiceFactory();

		return serviceFactory.getRegulationService();
	}

	// 获取发送消息服务对象
	private ITaskMessageService getTaskMessageService() {

		ServiceFactory serviceFactory = ServiceFactoryImpl.getServiceFactory();

		return serviceFactory.getTaskMessageService();
	}

	// 获取授权管理服务对象
	private IAuthorizedManagement getAuthorizedmanagement() {

		ServiceFactory serviceFactory = ServiceFactoryImpl.getServiceFactory();

		return serviceFactory.getAuthorizedManagement();

	}

	public void taskHasten(List hasten, Assignable assignable, String hastenTemplate, Map replace) {
		// TODO Auto-generated method stub

	}

	public void assignParticipatorForDynamicTask(String arg0) {
		// TODO Auto-generated method stub

	}

	public void assignParticipatorForDynamicTask(List arg0) {
		// TODO Auto-generated method stub

	}

	public void dynamicCreateTask(DynamicTaskInfo arg0, TaskHastenInfo arg1) {
		// TODO Auto-generated method stub

	}

}
